/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Core;
using NUnit.Framework;
using Madason.MetaModel.Interfaces;
using System.IO;


namespace Madason.MetaModel.Interfaces.Tests
{
	[TestFixture]
	public class TestImportXmi11Classes
	{
		string simpleXmiWithClass =
			@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
			@"	<UML:Class xmi.id=""UMLClass.3"" xmlns:UML=""href://org.omg/UML/1.3"" name=""Expense"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" participant=""UMLAssociationEnd.74"" isActive=""false"">" +
			@"		<UML:Classifier.feature>"+
			@"			<UML:Attribute xmi.id=""UMLAttribute.4"" name=""ExpenseID"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" type=""X.96"" owner=""UMLClass.3""/>"+
			@"			<UML:Attribute xmi.id=""UMLAttribute.5"" name=""Date"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" type=""X.93"" owner=""UMLClass.3""/>"+
			@"		</UML:Classifier.feature>"+
			@"	</UML:Class>"+
			@"	<UML:Stereotype xmi.id=""X.87"" name=""entity"" extendedElement=""UMLClass.3 UMLClass.18 UMLClass.32 UMLClass.46 UMLClass.55""/>"+
			@"</XMI.content>";


		// a second vaiation to reflect stereotypes (used for enterprise architect)
		string simpleXmiWithClass2 =
			@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
			@"	<UML:Class xmi.id=""UMLClass.3"" xmlns:UML=""href://org.omg/UML/1.3"" name=""Expense"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" participant=""UMLAssociationEnd.74"" isActive=""false"">" +
			@"		<UML:Stereotype name=""entity""/>" +
			@"		<UML:Classifier.feature>" +
			@"			<UML:Attribute xmi.id=""UMLAttribute.4"" name=""ExpenseID"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" owner=""UMLClass.3"">" +
			@"				<UML:StructuralFeature.type>" +
			@"					<UML:Classifier xmi.idref=""X.96""/>" +
			@"				</UML:StructuralFeature.type>" +
			@"          </UML:Attribute>" + 
			@"			<UML:Attribute xmi.id=""UMLAttribute.5"" name=""Date"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" type=""X.93"" owner=""UMLClass.3""/>" +
			@"		</UML:Classifier.feature>" +
			@"	</UML:Class>" +
			@"</XMI.content>";


		protected Model LoadModel(string xmlData)
		{
			ImportXmi11 import = new ImportXmi11();
			StringReader reader = new StringReader(xmlData);
			Model model = import.Import(reader);
			Assert.IsNotNull(model);
			return model;
		}

		[Test]
		public void TestLoadClass()
		{
			Model model = LoadModel(simpleXmiWithClass);
			Assert.AreEqual(1, model.Classes.Count);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual("UMLClass.3", cls.Id);
			Assert.AreEqual("Expense", cls.Name);

		}
		
		[Test]
		public void TestClassStereotype()
		{
			Model model = LoadModel(simpleXmiWithClass);
			Assert.AreEqual(1, model.Classes.Count);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual("entity", cls.StereotypeName);			
		}


		[Test]
		public void TestClassStereotype2()
		{
			Model model = LoadModel(simpleXmiWithClass2);
			Assert.AreEqual(1, model.Classes.Count);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual("entity", cls.StereotypeName);
		}


		[Test]
		public void TestSuperClass()
		{
			string xmiSubclass =
				@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
				@"	<UML:Class xmi.id=""UMLClass.3"" name=""Superclass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" specialization=""UMLGeneralization.5"" isActive=""false""/>"+
				@"	<UML:Class xmi.id=""UMLClass.4"" name=""Subclass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" generalization=""UMLGeneralization.5"" isActive=""false""/>"+
				@"	<UML:Generalization xmi.id=""UMLGeneralization.5"" name="""" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" discriminator="""" child=""UMLClass.4"" parent=""UMLClass.3""/>"+
				@"</XMI.content>";


			Model model = LoadModel(xmiSubclass);
			Assert.AreEqual(2, model.Classes.Count);
			Class subclass = model.FindClassById("UMLClass.4");
			Class superclass = model.FindClassById("UMLClass.3");
			Assert.AreEqual("Subclass", subclass.Name);
			Assert.AreEqual("Superclass", superclass.Name);
			
			Assert.IsNotNull(subclass.SuperClass);
			Assert.AreEqual(1, superclass.SubClasses.Count);
			Assert.AreEqual(subclass, superclass.SubClasses[0]);
		}

		[Test]
		public void TestClassTaggedValue()
		{
			string xmiTaggedValue =
				@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
				@"<UML:Class xmi.id=""UMLClass.3"" name=""TestClass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" isActive=""false""/>" +
				@"<UML:TaggedValue xmi.id=""X.4"" tag=""table"" value=""SomeInformation"" modelElement=""UMLClass.3""/>" +
				@"</XMI.content>";


			Model model = LoadModel(xmiTaggedValue);
			Assert.AreEqual(1, model.Classes.Count);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(1, cls.TaggedValues.Count);
			TaggedValue tv = cls.TaggedValues[0] as TaggedValue;
			Assert.AreEqual("table", tv.Key);
			Assert.AreEqual("SomeInformation", tv.Value);
		}

		
		/// <summary>
		/// this syntax is used by eanterprise architect
		/// </summary>
		[Test]
		public void TestClassTaggedValue2()
		{
			string xmiTaggedValue =
				@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
				@"<UML:Class xmi.id=""UMLClass.3"" name=""TestClass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" isActive=""false"">" +
				@"  <UML:TaggedValue tag=""table"" value=""SomeInformation""/>" +
				@"</UML:Class>"+
				@"</XMI.content>";


			Model model = LoadModel(xmiTaggedValue);
			Assert.AreEqual(1, model.Classes.Count);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(1, cls.TaggedValues.Count);
			TaggedValue tv = cls.TaggedValues[0] as TaggedValue;
			Assert.AreEqual("table", tv.Key);
			Assert.AreEqual("SomeInformation", tv.Value);
		}

	}
}
